package xcu.lxj.nettychat.websocket.netty;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleStateEvent;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import xcu.lxj.nettychat.user.service.inter.WebSocketService;

/**
 * @Author XinJian Lei
 * @Date 2024/9/15 16:44
 * @Version 1.0
 */
@Slf4j
@Sharable
public class WebSocketMessageHandle extends SimpleChannelInboundHandler<TextWebSocketFrame> {


    private WebSocketService webSocketService;

    // 读取客户端的信息做出回应
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        log.info("channelRead0 客户端 发送过来的消息 : {}",msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(msg.text())));
    }

    /**
     * 请求到达的时候获取 webSocketService
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        this.webSocketService =  SpringUtil.getBean(WebSocketService.class);

    }

    // 客户端离线
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        userOffLine(ctx);
    }

    // 通道掉线
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 可能出现业务判断离线后再次触发 channelInactive
        Long attr = NettyAttrUtils.getAttr(ctx.channel(), NettyAttrUtils.UID);
        log.warn("触发 channelInactive 掉线![用户id = {}]", attr);
//        userOffLine(ctx);
    }

    // 异常捕获
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.warn(" exceptionCaught 异常发生，异常消息 = {}", cause);
        ctx.channel().close();
    }

    // 事件监听
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if( evt instanceof IdleStateEvent){
            //心跳检测事件
            log.info("userEventTriggered {} 用户发生读写超时 ",NettyAttrUtils.getAttr(ctx.channel(),NettyAttrUtils.UID));
//            this.userOffLine(ctx);
        }
        // 握手完成会 传递过来的事件
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
//            log.info("握手完成 等待进行校验token = {}",NettyAttrUtils.getAttr(ctx.channel(),NettyAttrUtils.TOKEN));
            String token = NettyAttrUtils.getAttr(ctx.channel(), NettyAttrUtils.TOKEN);
            // 把token 传入做 验证 和 验证后 的处理
            if(StringUtil.isNotBlank(token)){
                webSocketService.authorize(ctx.channel(), token);
            }else {
                this.userOffLine(ctx);
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    /**
     *  用户连接关闭
     * @param ctx
     */
    private void userOffLine(ChannelHandlerContext ctx) {
        this.webSocketService.removed(ctx.channel());
    }

}
